/*
	*@brief				:pthread_cleanup_push()和 pthread_cleanup_pop()分别负责向调用线程的清理函数栈中添加和移除清理函数

	*@param[routine]	:routine 是一个函数指针，指向一个需要添加的清理函数;
	*@param[arg]		:当调用清理函数 routine()时， 将 arg 作为 routine()函数的参数。

	*@others			:1.	当线程执行以下动作时，清理函数栈中的清理函数才会被执行：
							线程调用 pthread_exit()退出时；
							线程响应取消请求时；
							用非 0 参数调用 pthread_cleanup_pop()

						2.	必须一一对应着来使用
 */
//void pthread_cleanup_push(void (*routine)(void *), void *arg);
//void pthread_cleanup_pop(int execute);

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>

static void cleanup(void *arg)
{
	printf("cleanup: %s\n", (char *)arg);
}

static void *new_thread_start(void *arg)
{
	puts("新线程--start run");

	pthread_cleanup_push(cleanup, "第 1 次调用");
	pthread_cleanup_push(cleanup, "第 2 次调用");
	pthread_cleanup_push(cleanup, "第 3 次调用");

	pthread_cleanup_pop(1);//传入非零值，清理函数工作，执行最顶层的清除函数

	puts("===================");

	sleep(2);
	pthread_exit((void *)0); //线程终止， 如果这里调用return，发现并不会执行清理函数。

	/* 为了与 pthread_cleanup_push 配对,不添加程序编译会通不过 */
	//线程退出开始执行
	pthread_cleanup_pop(0);
	pthread_cleanup_pop(0);
}

int main(void)
{
	pthread_t tid;
	void *tret;
	int ret;

	//申请一个线程
	ret = pthread_create(&tid, NULL, new_thread_start, NULL);
	if (ret)
	{
		fprintf(stderr,"pthread_create error:%s\n",strerror(ret));
		exit(-1);
	}

	//回收一个线程
	ret = pthread_join(tid, &tret);
	if (ret)
	{
		fprintf(stderr, "pthread_join error:%s\n", strerror(ret));
		exit(-1);
	}

	printf("新线程终止, code=%ld\n", (long)tret);

	exit(0);
}